﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;

namespace WebClient
{
    public class FormSerialize
    {
        private Dictionary<string, Func<object, object>> ConvertMapping = new Dictionary<string, Func<object, object>>();

        public FormSerialize(Form form)
        {

            this.form = form;

            InitConvertMapping();
            InitFormData();
        }

        private void InitFormData()
        {
            var system_dic = SystemConfigHelper.GetInstance().GetSetting("System");
            if (system_dic != null && system_dic.ContainsKey("FormAttributeNames"))
            {
                var names = system_dic["FormAttributeNames"].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                FormAttribute = names;
            }
            else
            {
                FormAttribute = new List<string>();
            }
        }

        private void InitConvertMapping()
        {
            ConvertMapping.Add(GetCacheKey(typeof(Size), typeof(string)), (obj) =>
            {
                var size = (Size)obj;
                return string.Format("{0},{1}", size.Width, size.Height);
            });

            ConvertMapping.Add(GetCacheKey(typeof(string), typeof(Size)), (obj) =>
            {
                var str = (string)obj;

                int width = 0, height = 0;
                var str_items = str.Split(',');
                int.TryParse(str_items[0], out width);
                int.TryParse(str_items[1], out height);

                Size size = new Size(width, height);
                return size;
            });

            ConvertMapping.Add(GetCacheKey(typeof(string), typeof(Uri)), (obj) =>
            {
                var str = (string)obj;
                if (string.IsNullOrEmpty(str))
                    return null;

                return new Uri(str);
            });

            ConvertMapping.Add(GetCacheKey(typeof(Uri), typeof(string)), (obj) => { return ((Uri)obj).ToString(); });
            ConvertMapping.Add(GetCacheKey(typeof(string), typeof(Point)), (obj) =>
            {
                var str = (string)obj;

                int x = 0, y = 0;
                var str_items = str.Split(',');
                int.TryParse(str_items[0], out x);
                int.TryParse(str_items[1], out y);

                Point size = new Point(x, y);
                return size;
            });

            ConvertMapping.Add(GetCacheKey(typeof(Point), typeof(string)), (obj) =>
            {
                Point po = (Point)obj;
                return string.Format("{0},{1}", po.X, po.Y);
            });

            ConvertMapping.Add(GetCacheKey(typeof(string), typeof(FormWindowState)), (obj) =>
            {
                string str = (string)obj;
                return Enum.Parse(typeof(FormWindowState), str);
            });
        }

        private Form form = null;

        /// <summary>
        /// 界面的相关属性
        /// </summary>
        public IEnumerable<string> FormAttribute { get; set; }

        private string GetTypeName(Type t)
        {
            return t.ToString();
        }

        private string GetCacheKey(Type a, Type b)
        {
            return string.Format("{0}=>{1}", GetTypeName(a), GetTypeName(b));
        }

        /// <summary>
        /// 转换数据类型
        /// </summary>
        /// <param name="data"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private object ConvertData(object data, Type type)
        {
            if (data == null)
                return null;

            var data_type = data.GetType();
            string cache_key = GetCacheKey(data_type, type);

            if (ConvertMapping.ContainsKey(cache_key))
            {
                return ConvertMapping[cache_key](data);
            }
            else
            {
                return Convert.ChangeType(data, type);
            }
        }

        /// <summary>
        /// 序列化
        /// </summary>
        public void Serialize()
        {
            if (form == null)
                return;

            var form_type = form.GetType();

            Dictionary<string, string> dic = new Dictionary<string, string>();

            foreach (var item in FormAttribute ?? new List<string>())
            {
                var field = form_type.GetProperty(item);
                if (field == null)
                    continue;

                var value = field.GetValue(form);

                dic.Add(item, (string)ConvertData(value, typeof(string)));
            }

            SystemConfigHelper.GetInstance().SetSetting("Form", dic);
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        public void DeSerialize()
        {
            if (form == null)
                return;

            var form_type = form.GetType();

            var web_dic = SystemConfigHelper.GetInstance().GetSetting("Web");
            foreach (var item in web_dic)
            {
                var field = form_type.GetProperty(item.Key);

                if (field == null)
                    continue;

                field.SetValue(form, ConvertData(item.Value, field.PropertyType));
            }

            var form_dic = SystemConfigHelper.GetInstance().GetSetting("Form");
            foreach (var item in form_dic)
            {
                if (FormAttribute.Contains(item.Key))
                {
                    var field = form_type.GetProperty(item.Key);
                    field.SetValue(form, ConvertData(item.Value, field.PropertyType));
                }
            }
        }
    }
}
